package com.open.server.api.system;


import com.open.base.utils.UserHolderUtils;
import com.open.base.interceptor.PermissionInterceptor;
import com.open.base.model.Menu;
import com.open.base.model.User;
import com.open.common.annotation.InterfaceExtend;
import com.open.common.annotation.MethodPermission;
import com.open.common.constants.SysCode;
import com.open.common.model.Page;
import com.open.common.model.PageRequest;
import com.open.common.model.Result;
import com.open.common.utils.ExcelUtils;
import com.open.common.utils.ThrowUtils;
import com.open.system.dispatch.IUserDispatch;
import com.open.system.model.dto.ImportResultDto;
import com.open.system.model.dto.PassWordDto;
import com.open.system.model.dto.UserExcelDto;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户信息
 *
 * @author 大树03
 * @date 2025-02-01 22:47
 */
@RestController
@RequestMapping("/system/user")
public class UserApi {

    @Autowired
    private IUserDispatch userDispatch;

    /**
     * 对象添加
     *
     * @param model 添加的对象
     * @return
     */
    @MethodPermission("user_add")
    @PostMapping("save")
    public Result<User> save(@RequestBody User model) {
        long now = System.currentTimeMillis();
        Result<User> result = new Result<>();
        userDispatch.save(model);
        result.setData(model);
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }

    /**
     * 对象修改
     *
     * @param model 修改的对象
     * @return
     */
    //@MethodPermission("user_update")
    @PostMapping("update")
    public Result<Boolean> update(@RequestBody User model) {
        //更新个人信息，不校验权限
        if (!Objects.equals(model.getId(), UserHolderUtils.getUserId())) {
            PermissionInterceptor permissionInterceptor = new PermissionInterceptor();
            List<String> permissions = UserHolderUtils.getPermissions().stream().map(Menu::getPermissionVal).collect(Collectors.toList());
            //如果没权限,直接抛异常,让全局业务异常捕获器捕获,返回对应的状态码
            ThrowUtils.throwIf(!permissionInterceptor.hasThisPrivilege(permissions, "user_update"), "无权限，请联系管理员授权", SysCode.FORBIDDEN);
        }
        long now = System.currentTimeMillis();
        Result<Boolean> result = new Result<>();
        result.setData(userDispatch.update(model));
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }

    /**
     * 根据对象列表查询
     *
     * @param model 查询条件
     * @return
     */
    @PostMapping("findByModel")
    public Result<List<User>> findByModel(@RequestBody User model) {
        long now = System.currentTimeMillis();
        Result<List<User>> result = new Result<>();
        result.setData(userDispatch.findByModel(model));
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }

    /**
     * 根据主键查询对象
     *
     * @param id 查询的对象主键
     * @return
     */
    @GetMapping("findByPk")
    public Result<User> findByPk(@RequestParam("id") Long id) {
        long now = System.currentTimeMillis();
        Result<User> result = new Result<>();
        result.setData(userDispatch.findByPk(id));
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }

    /**
     * 分页查询
     *
     * @param pageRequest 分页查询条件
     * @return
     */
    @MethodPermission("user_query")
    @InterfaceExtend(title = "分页查询")
    @PostMapping("findPage")
    public Result<Page<User>> findPage(@RequestBody PageRequest<User> pageRequest) {
        long now = System.currentTimeMillis();
        Result<Page<User>> result = new Result<>();
        result.setData(userDispatch.findPage(pageRequest.getPage(), pageRequest.getModel()));
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }

    /**
     * 根据主键删除对象
     *
     * @param ids 删除的对象主键
     * @return
     */
    @MethodPermission("user_delete")
    @GetMapping("remove")
    public Result<Boolean> remove(@RequestParam("ids") List<Long> ids) {
        long now = System.currentTimeMillis();
        Result<Boolean> result = new Result<>();
        result.setData(userDispatch.remove(ids));
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }

    /**
     * 重置密码
     *
     * @param pwd
     * @return
     */
    @PostMapping("resetPwd")
    //@MethodPermission("user_update")
    public Result<Boolean> resetPwd(@RequestBody PassWordDto pwd) {
        long now = System.currentTimeMillis();
        Result<Boolean> result = new Result<>();
        result.setData(userDispatch.resetPwd(pwd));
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }

    /**
     * 导出用户数据
     *
     * @param response HttpServletResponse
     */
    @MethodPermission("user_query")
    @GetMapping("export")
    public void export(HttpServletResponse response) {
        List<User> userList = userDispatch.findByModel(new User());

        List<UserExcelDto> excelDataList = userList.stream()
                .map(user -> {
                    UserExcelDto dto = new UserExcelDto();
                    BeanUtils.copyProperties(user, dto);
                    return dto;
                })
                .collect(Collectors.toList());

        byte[] bytes = ExcelUtils.exportExcelToBytes(excelDataList, UserExcelDto.class, "用户列表");
        // 输出到response
        ExcelUtils.genCode(response, bytes, "用户数据.xlsx");
    }

    /**
     * 导出用户数据模板
     *
     * @param response HttpServletResponse
     */
    @MethodPermission("user_query")
    @GetMapping("exportTemplate")
    public void exportTemplate(HttpServletResponse response) {
        // 生成空模板的byte数组（传入null表示空数据）
        byte[] bytes = ExcelUtils.exportExcelToBytes(null, UserExcelDto.class, "用户列表");
        ExcelUtils.genCode(response, bytes, "export_template.xlsx");
    }

    /**
     * 导入用户数据
     * 如果有错误，返回JSON包含错误日志
     *
     * @param file 上传的Excel文件
     * @return 导入结果
     */
    @MethodPermission("user_add")
    @PostMapping("import")
    public Result<String> importData(@RequestParam("file") MultipartFile file) {
        long now = System.currentTimeMillis();
        Result<String> result = new Result<>();
        ImportResultDto importResult = userDispatch.importData(file);
        result.setData(importResult.getResultMessage());
        result.setTime(System.currentTimeMillis() - now);
        return result;
    }
}